home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 4
/
FM Towns Free Software Collection 4 - Disc 1.iso
/
t_os
/
wstype
/
source
/
tree.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-18
|
7KB
|
367 lines
/*** [tree.c]
*
* ディレクトリツリー情報 関連 (C)ささがわ
*
* For GNU C Compiler (GCC) Version 1.39
*
***/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
#include <dos.h>
#include "tree.h"
#include "others.h"
#define DEFAULT_BUF 150 /* 初期のバッファサイズ */
#define ADD_BUF 50 /* 追加バッファサイズ */
#define DRBUFDEF 50 /* 初期のバッファサイズ */
#define DRBUFADD 30 /* 追加バッファサイズ */
static struct tree_t *trbuf;
static int cap, nest, mnest;
static int bufoff, bufsz;
static int DRbuf_sz, DRbuf_err;
static unsigned short DRbuf_tab[40], DRbuf_num[40];
static char (*DRbuf)[13];
static int (*TR_break)(void);
static int Set_tree(void);
static int Buf_extend(void);
static int Set_tree_sub(void);
static int Get_subdir(int, char *);
static int Get_subdir_sub(int, char *);
static int DRbuf_extend(void);
/***
* ディレクトリツリー格納関数
* 入力: dt:ツリー情報構造体へのポインタ bt:中断用関数へのポインタ
* 戻り値: 0 正常終了 -1 メモリーエラー -2 ディスクエラー -3 中断
***/
int Get_dirtree(struct dirtree_t *dt, int c, int (*br)(void)) {
int ret;
cap = c;
TR_break = br;
if ((DRbuf = malloc(13 * DRBUFDEF)) == NULL) {
DRbuf_sz = 0;
DRbuf_err = 1;
} else {
DRbuf_sz = DRBUFDEF;
DRbuf_tab[0] = 0;
DRbuf_err = 0;
}
bufsz = DEFAULT_BUF;
while ((ret = Set_tree()) == -4);
if (ret != 0) {
dt->tr = NULL;
dt->numd = -1;
dt->numc = -1;
} else {
int i;
unsigned char branch[40];
dt->tr = trbuf;
dt->numd = bufoff;
dt->numc = mnest + 1;
for (i = 0; i < 40; i++)
branch[i] = 0;
for (i = 0; i < dt->numd; i++) {
branch[trbuf[i].nest - 1] = 1;
TR_branch(0, branch, trbuf[i].branch);
if (trbuf[i].dirn == 0xffff)
branch[trbuf[i].nest - 1] = 0;
}
}
free(DRbuf);
return ret;
}
/* バッファ格納関数 */
static int Set_tree(void) {
int ret;
char dir[70];
TR_bufrel();
bufoff = 0;
if ((trbuf = (struct tree_t *)malloc(bufsz * sizeof(struct tree_t))) == NULL)
return -1;
dir[0] = '\\';
if (Get_curdir(0, dir + 1) || chdir("\\"))
return -2;
nest = 0;
mnest = 0;
trbuf[bufoff].nest = (unsigned char)nest++;
trbuf[bufoff].dirn = 0xffff;
strcpy(trbuf[bufoff++].name, "\\");
ret = Set_tree_sub();
if (ret != -2 && chdir(dir))
return -2;
return ret;
}
static int Buf_extend(void) {
int p;
void *buf2;
p = bufsz;
bufsz += ADD_BUF;
if ((buf2 = malloc(bufsz * sizeof(struct tree_t))) == NULL)
return -1;
memcpy(buf2, trbuf, p * sizeof(struct tree_t));
free(trbuf);
trbuf = buf2;
return 0;
}
/* ディレクトリ再帰関数 */
/* 戻り値:0 正常終了 -4 リトライ -2 ディスクエラー -3 中断 */
static int Set_tree_sub(void) {
int ret, dirn = 0, p = -1;
char buf[15];
if (TR_break())
return -3;
while (Get_subdir(dirn, buf)) {
p = bufoff++;
trbuf[p].nest = (unsigned char)nest;
trbuf[p].dirn = dirn++;
if (!cap)
strlow(0, (unsigned char *)buf);
strcpy(trbuf[p].name, buf);
if (bufoff >= bufsz) {
if (Buf_extend())
return -4;
}
if (chdir(buf))
return -2;
nest++;
if (ret = Set_tree_sub())
return ret;
}
if (TR_break())
return -3;
if (p >= 0) {
trbuf[p].dirn = 0xffff;
if (nest > mnest)
mnest = nest;
}
if (nest > 1) {
if (chdir(".."))
return -2;
nest--;
}
return 0;
}
/* カレントディレクトリ中のnd番目のサブディレクトリを検索する関数 */
/* 見つかった場合はbufに格納し, 戻り値に1を返す */
static int Get_subdir(int nd, char *buf) {
int ret;
if (nd == 0) {
int p, err = 0;
struct find_t ft;
p = DRbuf_tab[nest - 1];
if (!_dos_findfirst("*.*", _A_SUBDIR, &ft)) {
if (ft.name[0] != '.' && ft.attrib & _A_SUBDIR) {
if (p >= DRbuf_sz)
err = DRbuf_extend();
if (!err)
strcpy((char *)(DRbuf + p++), ft.name);
}
while (!err && !_dos_findnext(&ft)) {
if (ft.name[0] != '.' && ft.attrib & _A_SUBDIR) {
if (p >= DRbuf_sz)
err = DRbuf_extend();
if (!err)
strcpy((char *)(DRbuf + p++), ft.name);
}
}
}
if (err) {
DRbuf_tab[nest] = DRbuf_tab[nest - 1];
DRbuf_num[nest - 1] = 0xffff;
if (Get_subdir_sub(0, buf))
ret = 1;
else
ret = 0;
} else {
DRbuf_tab[nest] = p;
if ((DRbuf_num[nest - 1] = DRbuf_tab[nest] - DRbuf_tab[nest - 1]) != 0) {
strcpy(buf, DRbuf[DRbuf_tab[nest - 1]]);
ret = 1;
} else {
ret = 0;
}
}
} else {
if (DRbuf_num[nest - 1] == 0xffff) {
if (Get_subdir_sub(nd, buf))
ret = 1;
else
ret = 0;
} else if (nd > DRbuf_num[nest - 1] - 1) {
ret = 0;
} else {
strcpy(buf, DRbuf[DRbuf_tab[nest - 1] + nd]);
ret = 1;
}
}
return ret;
}
static int Get_subdir_sub(int nd, char *buf) {
int nd2 = 0;
struct find_t ft;
if (!_dos_findfirst("*.*", _A_SUBDIR, &ft)) {
if (ft.name[0] != '.' && ft.attrib & _A_SUBDIR) {
if (nd2 == nd) {
strcpy(buf, ft.name);
return 1;
}
nd2++;
}
while (!_dos_findnext(&ft)) {
if (ft.name[0] != '.' && ft.attrib & _A_SUBDIR) {
if (nd2 == nd) {
strcpy(buf, ft.name);
return 1;
}
nd2++;
}
}
}
return 0;
}
static int DRbuf_extend(void) {
void *tmp;
if (DRbuf_err || (tmp = malloc((DRbuf_sz + DRBUFADD) * 13)) == NULL) {
DRbuf_err = 1;
return -1;
}
memcpy(tmp, DRbuf, DRbuf_sz * 13);
free(DRbuf);
DRbuf = tmp;
DRbuf_sz += DRBUFADD;
return 0;
}
/* ツリー情報用バッファを開放する関数 */
void TR_bufrel(void) {
free(trbuf);
trbuf = NULL;
}
void TR_branch(int mode, unsigned char *byt, unsigned char *bit) {
int i;
if (mode) {
for (i = 0; i < 40; i++) {
if (bit[i / 8] >> i % 8 & 1)
byt[i] = 1;
else
byt[i] = 0;
}
} else {
for (i = 0; i < 5; i++)
bit[i] = 0;
for (i = 0; i < 40; i++) {
if (byt[i])
bit[i / 8] += (unsigned char)(1 << i % 8);
}
}
}
int TR_Search_curd(int mode, int *curd, char *dir, struct dirtree_t *dt) {
int ret;
if (mode) {
int n = -1, nest = 0, flag, len;
char *ptr;
ptr = strchr(dir, '\\');
len = 1;
do {
int i;
flag = 0;
do {
while (dt->tr[++n].nest != (unsigned char)nest);
if (strncmp(ptr, dt->tr[n].name, len) == 0) {
flag = 1;
break;
}
} while (dt->tr[n].dirn != 0xffff);
if (!flag)
break;
i = (int)strchr(ptr, '\\');
(i == 0) ? (ptr = strchr(ptr, '\0')) : (ptr = (char *)i + 1);
i = (int)strchr(ptr, '\\');
(i == 0) ? (len = strlen(ptr)) : (len = (char *)i - ptr);
nest++;
} while (*ptr != '\0');
if (flag) {
ret = 1;
*curd = n;
} else {
ret = 0;
*curd = -1;
}
} else {
int i, nst;
char *p, buf[70], buf2[70];
strcpy(buf, dt->tr[*curd].name);
if (dt->tr[*curd].nest != 0)
strcat(buf, "\\");
nst = dt->tr[*curd].nest;
for (i = *curd - 1; i > 0; i--) {
if (nst <= dt->tr[i].nest)
continue;
strcat(strcat(buf, dt->tr[i].name), "\\");
nst--;
}
strcpy(buf2, "\\");
p = strchr(buf, '\0');
for (i = 0; i < dt->tr[*curd].nest; i++) {
int l;
l = (int)p;
while (--p > buf && p[-1] != '\\');
l -= (int)p;
strncat(buf2, p, l);
}
if (dt->tr[*curd].nest != 0)
strchr(buf2, '\0')[-1] = '\0';
strcpy(dir, buf2);
ret = 1;
}
return ret;
}